package com.dospyer.provider.api;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
 * 1. ConsumerApplication 类上的 @EnableFeignClients 注解上 Import 了 FeignClientsRegistrar【@Import(FeignClientsRegistrar.class)】
 * 2. FeignClientsRegistrar 实现了 ImportBeanDefinitionRegistrar 接口，spring 容器初始化的时候会回调 registerBeanDefinitions 方法。
 *    spring 容器 refresh() 中的 invokeBeanFactoryPostProcessors(beanFactory) 方法，调用 invokeBeanDefinitionRegistryPostProcessors
 * 3. registerBeanDefinitions 方法中完成包扫描，创建 BeanDefinition 并添加到 registry 的 beanBeanDefinitionNames 中（registerClientConfiguration 和 registerClientConfiguration）。
 * 4. 实例化的时候会调用 FeignClientFactoryBean 的 getObject 方法（步骤3创建 BeanDefinition 时设置好的）
 *    4.1 getObject 方法中先从容器中获取 FeignContext （FeignAutoConfiguration 中实例化）
 *    4.2 基于 FeignContext 为每个 FeignClient 创建独立的容器， 并创建好 Feign.Builder（HystrixFeign.Builder，HystrixFeignConfiguration 中实例化）。
 *        为每个 Builder 设置独立的 logger、Encoder、Decoder、Contract
 *        configureFeign(context, builder) 方法中为 Feign.Builder 设置配置信息。
 *            配置优先级如下：1. configuration中配置优先级最低 2. application.yaml 中 feign.client 中 default 参数配置优先级中级 3. application.yaml 中 feign.client 中 服务相关的参数配置优先级最高
 * 5. loadBalance(builder, context, new HardCodedTarget<>(this.type,this.name, url));
 *     5.1 HardCodedTarget 中包含了 包含了接口类型（FeignService）、服务名称（provider）、url地址（http://provider）
 *
 *     5.2 Client client = getOptional(context, Client.class); 创建 LoadBalancerFeignClient（DefaultFeignLoadBalancedConfiguration 中实例化） 并设置给 Feign.Builder
 *     5.3 Targeter targeter = get(context, Targeter.class);  创建 HystrixTargeter（HystrixFeignTargeterConfiguration 中实例化）。
 *
 *     5.4 targeter.target(this, builder, context, target); 基于 Targeter 创建动态代理对象
 *     HystrixTargeter.class
 *     if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
 * 			return feign.target(target);
 *     }
 */

/**
 * fallback 处理程序异常
 * blockHandler：处理限流、熔断错误
 */

@FeignClient(value = "provider", fallback = ProviderApiFallback.class)
public interface ProviderApi {

    @GetMapping(value = "/sayHello/{id}")
    String sayHello(@PathVariable("id") Long id, @RequestParam("name") String name, @RequestParam("age") Integer age);

    @PostMapping(value = "/")
    String createUser(@RequestBody User user);

}
